#!/usr/bin/env python2
'''
Created on 10/25/14

@author : Rich Plevin
'''

# TBD: Although this seemed like a useful idea, it uses too much of the MCS system to run standalone.
# TBD: Better to just use this from within gcammcs.

import os
import argparse
from gcammcs.Package import GcamConfiguration, getConfigManager
from gcammcs.Scenario import ScenarioFile

DEFAULT_SECTION = 'DEFAULT'
GCAM_SECTION    = 'GCAM'
CONFIG_FILE     = '.gcam.cfg'


ConfigDefaults = \
"""
GCAM.Root           = %(Home)s/GCAM
GCAM.Current        = %(GCAM.Root)s/current
GCAM.Workspace      = %(GCAM.Current)s/Main_User_Workspace
GCAM.ScenariosDir   = %(GCAM.Root)s/mcs/scenarios
GCAM.ScenariosFile  = %(GCAM.ScenariosDir)s/scenarios.xml
GCAM.ConfigBasePath = %(GCAM.ScenariosDir)/configuration_ref.xml

GCAM.ModelInterface = %(GCAM.Current)s/ModelInterface
GCAM.JarFile        = %(GCAM.ModelInterface)s/ModelInterface.app/Contents/Resources/Java/ModelInterface.jar
GCAM.JavaLibPath    = %(GCAM.Workspace)s/libs/dbxml/lib
GCAM.OutputDir      = %(GCAM.Workspace)s/output
GCAM.XmlDatabase    = %(GCAM.Workspace)s/output/database.dbxml
GCAM.BatchFile      = generated_batch_file.xml

GCAM.DefaultApp     = gcamtest

[GCAM]
# Add customizations here, e.g., set GCAM.Root to another directory
"""

def parseArgs(defaultApp):
    parser = argparse.ArgumentParser()

    # Positional args
    parser.add_argument('scenarioFile', type=str,
                        help="The name of the XML file holding scenario definitions")

    # Optional args
    parser.add_argument('-A', '--appName', default=defaultApp,
                        help='Name of user application name. (Defaults to the value of config parameter DefaultApp.)')
    parser.add_argument('-b', '--baseConfig', type=str, default="",
                        help='''The base configuration file against which edits are made to generate scenario config files.
                                (Defaults to value of config parameter GCAM.ConfigBasePath.)''')
    parser.add_argument('-d', '--scenariosDir', type=str, default="",
                        help='''The directory into which scenario config files should be written
                                (Defaults to value of config parameter GCAM.ScenarioDir.)''' )
    parser.add_argument('-m', '--make', dest='makeOnly', action='store_true',
                        help="Make all scenario config files but don't run GCAM.")
    parser.add_argument('-n', '--noExec', action='store_true',
                        help='Print generated shell commands and exit.')
    parser.add_argument('-s', '--scenarios', type=str, default=None,
                        help='Comma-delimited list of scenarios to process (overridden by -a flag)')
    parser.add_argument('--verbose', '-v', action='count',
                        help="Show commands being executed.")


    args = parser.parse_args()
    return args


def main():
    cfg = getConfigManager(GcamConfiguration)
    args = parseArgs(defaultApp)

    home = os.getenv('HOME')
    configPath = os.path.join(home, CONFIG_FILE)

    if not os.path.exists(configPath):
        with open(configPath, 'w') as fp:
            fp.write("[%s]\n" % DEFAULT_SECTION)
            fp.write("Home = %s\n" % home)
            fp.write(ConfigDefaults)

    parser = SafeConfigParser()
    parser.readfp(open(configPath))

    def getParam(name):
        return parser.get(GCAM_SECTION, name)

    defaultApp = args.appName or getParam('GCAM.DefaultApp')

    programName = getParam('GCAM.ProgramName')

    # N.B. Scenario.makeShellCommand fills in various args from config file if are not specified here

    # For testing, use ./unittest/testFiles/scenarios.xml
    scenariosFile  = args.scenarioFile or getParam('GCAM.ScenariosFile')
    scenFileObj    = ScenarioFile(scenariosFile)
    scenarios      = args.scenarios.split(',') if args.scenarios else []

    scenFilename = scenFileObj.getFilename()
    basePath     = args.baseConfig
    scenarioDir  = args.scenariosDir
    runAll       = (len(scenarios) == 0)     # if no scenarios are named, we run all "active" ones
    execute      = not args.noExec
    generated    = False

    for scenario in scenFileObj.scenarioDict.values():
        if (runAll and scenario.active) or scenario.name in scenarios:
            cmd = scenario.shellCommand(baseConfigPath=basePath, scenarioDir=scenarioDir)
            configFile = scenario.configFile

            if not os.path.lexists(configFile) or \
                os.path.getmtime(scenFilename) > os.path.getmtime(configFile) or \
                os.path.getmtime(basePath)     > os.path.getmtime(configFile):

                generated = True
                if args.verbose or not execute:
                    print "Generating scenario config file: %s\n" % configFile
                    print "%s\n" % cmd    # these are long, so add vertical space

                if execute:
                    os.system(cmd)

            if not args.makeOnly:
                cmd = "./%s -C %s" % (programName ,configFile)
                if args.verbose or not execute:
                    print cmd

                if execute:
                    os.system(cmd)

    if args.makeOnly and not generated:
        print "All scenarios config files are up-to-date"


if __name__ == "__main__":
    main()
